#include "Wilcoxon.h"

Wilcoxon::Wilcoxon()
{
}

Wilcoxon::~Wilcoxon()
{
}

void Wilcoxon::swap(double& a, double& b)
{
    double temp;
    temp=a;
    a=b;
    b=temp;
    return;
}

double* Wilcoxon::abs_bubble_sort(double* Vector, int Size)
{
    for(int i=0;i<Size;i++)
        for(int j=i+1;j<Size;j++)
            if(abs(Vector[i])>abs(Vector[j]))
                Wilcoxon::swap(Vector[i], Vector[j]);
    return Vector; 
}

double* Wilcoxon::rank(double* Vector, int Size)
{
    double* Rank=new double[Size];
    double count=1;
    for(int i=0;i<Size;i++)
    {
        if(Vector[i]==0)
            Rank[i]=0.0;
        else
        {
            Rank[i]=count;
            count++;
        }
    }
    int first=0, last=first+1;
    double sum=0;
    do
    {
        if(Rank[first]==0){first++; last=first+1;}  //skip '0's
        else
        {
            if(abs(Vector[first])==abs(Vector[last])){sum+=Rank[last]; last++;}  //record rank sum
            else
            {
                sum=(double)(sum+Rank[first])/(last-first);
                for(int i=first; i<last; i++)
                    Rank[i]=(Vector[i]>0? sum:-sum);
                sum=0;
                first=last;
                last=first+1;
            }
        }
    }while(last!=Size);
    if(Rank[first]!=0)
    {    
        sum+=Rank[first];
        sum/=(double)(last-first);
        for(int i=first; i<last; i++)
            Rank[i]=(Vector[i]>0? sum:-sum);
    }
    return Rank;
}
             
double Wilcoxon::wilcoxon_signed_rank_test(double* Vector1, double* Vector2, int SampleSize)
{
    double* Diff=new double[SampleSize];
    double* Rank;
    memset(Diff, 0, sizeof(double)*SampleSize);
    for(int i=0;i<SampleSize;i++)
        Diff[i]=Vector1[i]-Vector2[i];
    Diff=abs_bubble_sort(Diff, SampleSize);
    Rank=rank(Diff, SampleSize);
    double W=0.0;
    for(int i=0;i<SampleSize;i++)
        W+=Rank[i];
    delete[] Diff;
    delete[] Rank;
    return W;
}

double Wilcoxon::wilcoxon_rank_sum_test(double* Vector1, double* Vector2, int SampleSize1, int SampleSize2)
{
    double W=0.0;
    for(int i=0;i<SampleSize1;i++)
    {
        for(int j=0;j<SampleSize2;j++)
        {
            if(Vector1[i]>Vector2[j])
                W++;
            if(Vector1[i]==Vector2[j])
                W+=0.5;
        }
    }
    if(W>=77)
        return 1.0;
    if(W<=23)
        return -1.0;
    if(W>23&&W<77)
        return 0.0;
}  
